home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / FLTK-1.0.6 / src / Fl_Tile.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-25  |  5.4 KB  |  200 lines

  1. //
  2. // "$Id: Fl_Tile.cxx,v 1.5.2.1 1999/05/25 05:33:56 bill Exp $"
  3. //
  4. // Tile widget for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-1999 by Bill Spitzak and others.
  7. //
  8. // This library is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU Library General Public
  10. // License as published by the Free Software Foundation; either
  11. // version 2 of the License, or (at your option) any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. // Library General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Library General Public
  19. // License along with this library; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. // USA.
  22. //
  23. // Please report all bugs and problems to "fltk-bugs@easysw.com".
  24. //
  25.  
  26. // Group of 2 or 4 "tiles" that can be resized by dragging border
  27. // The size of the first child determines where the resize border is.
  28. // The resizebox is used to limit where the border can be dragged to.
  29.  
  30. #include <FL/Fl.H>
  31. #include <FL/Fl_Tile.H>
  32. #include <FL/Fl_Window.H>
  33. #include <stdlib.h>
  34.  
  35. // Drag the edges that were initially at oldx,oldy to newx,newy:
  36. // pass zero as oldx or oldy to disable drag in that direction:
  37.  
  38. void Fl_Tile::position(int oix, int oiy, int newx, int newy) {
  39.   Fl_Widget*const* a = array();
  40.   short* p = sizes();
  41.   p += 8; // skip group & resizable's saved size
  42.   for (int i=children(); i--; p += 4) {
  43.     Fl_Widget* o = *a++;
  44.     if (o == resizable()) continue;
  45.     int X = o->x();
  46.     int R = X+o->w();
  47.     if (oix) {
  48.       int t = p[0];
  49.       if (t == oix || t>oix && X<newx || t<oix && X>newx) X = newx;
  50.       t = p[1];
  51.       if (t == oix || t>oix && R<newx || t<oix && R>newx) R = newx;
  52.     }
  53.     int Y = o->y();
  54.     int B = Y+o->h();
  55.     if (oiy) {
  56.       int t = p[2];
  57.       if (t == oiy || t>oiy && Y<newy || t<oiy && Y>newy) Y = newy;
  58.       t = p[3];
  59.       if (t == oiy || t>oiy && B<newy || t<oiy && B>newy) B = newy;
  60.     }
  61.     o->damage_resize(X,Y,R-X,B-Y);
  62.   }
  63. }
  64.  
  65. // move the lower-right corner (sort of):
  66. void Fl_Tile::resize(int X,int Y,int W,int H) {
  67.   // remember how much to move the child widgets:
  68.   int dx = X-x();
  69.   int dy = Y-y();
  70.   int dw = W-w();
  71.   int dh = H-h();
  72.   short* p = sizes();
  73.   // resize this (skip the Fl_Group resize):
  74.   Fl_Widget::resize(X,Y,W,H);
  75.   // find bottom-right of resiable:
  76.   int OR = p[5];
  77.   int NR = X+W-(p[1]-OR);
  78.   int OB = p[7];
  79.   int NB = Y+H-(p[3]-OB);
  80.   // move everything to be on correct side of new resizable:
  81.   Fl_Widget*const* a = array();
  82.   p += 8;
  83.   for (int i=children(); i--;) {
  84.     Fl_Widget* o = *a++;
  85.     int X = o->x()+dx;
  86.     int R = X+o->w();
  87.     if (*p++ >= OR) X += dw; else if (X > NR) X = NR;
  88.     if (*p++ >= OR) R += dw; else if (R > NR) R = NR;
  89.     int Y = o->y()+dy;
  90.     int B = Y+o->h();
  91.     if (*p++ >= OB) Y += dh; else if (Y > NB) Y = NB;
  92.     if (*p++ >= OB) B += dh; else if (B > NB) B = NB;
  93.     o->resize(X,Y,R-X,B-Y); o->redraw();
  94.   }
  95. }
  96.  
  97. static void set_cursor(Fl_Tile*t, Fl_Cursor c) {
  98.   static Fl_Cursor cursor;
  99.   if (cursor == c) return;
  100.   cursor = c;
  101. #ifdef __sgi
  102.   t->window()->cursor(c,FL_RED,FL_WHITE);
  103. #else
  104.   t->window()->cursor(c);
  105. #endif
  106. }
  107.  
  108. static Fl_Cursor cursors[4] = {
  109.   FL_CURSOR_DEFAULT,
  110.   FL_CURSOR_WE,
  111.   FL_CURSOR_NS,
  112.   FL_CURSOR_MOVE};
  113.  
  114. int Fl_Tile::handle(int event) {
  115.   static int sdrag;
  116.   static int sdx, sdy;
  117.   static int sx, sy;
  118. #define DRAGH 1
  119. #define DRAGV 2
  120. #define GRABAREA 4
  121.  
  122.   int mx = Fl::event_x();
  123.   int my = Fl::event_y();
  124.  
  125.   switch (event) {
  126.  
  127.   case FL_MOVE:
  128.   case FL_ENTER:
  129.   case FL_PUSH: {
  130.     int mindx = 100;
  131.     int mindy = 100;
  132.     int oldx = 0;
  133.     int oldy = 0;
  134.     Fl_Widget*const* a = array();
  135.     short* q = sizes();
  136.     short* p = q+8;
  137.     for (int i=children(); i--; p += 4) {
  138.       Fl_Widget* o = *a++;
  139.       if (o == resizable()) continue;
  140.       if (p[1]<q[1] && o->y()<=my+GRABAREA && o->y()+o->h()>=my-GRABAREA) {
  141.     int t = mx - (o->x()+o->w());
  142.     if (abs(t) < mindx) {
  143.       sdx = t;
  144.       mindx = abs(t);
  145.       oldx = p[1];
  146.     }
  147.       }
  148.       if (p[3]<q[3] && o->x()<=mx+GRABAREA && o->x()+o->w()>=mx-GRABAREA) {
  149.     int t = my - (o->y()+o->h());
  150.     if (abs(t) < mindy) {
  151.       sdy = t;
  152.       mindy = abs(t);
  153.       oldy = p[3];
  154.     }
  155.       }
  156.     }
  157.     sdrag = 0; sx = sy = 0;
  158.     if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oldx;}
  159.     if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oldy;}
  160.     set_cursor(this, cursors[sdrag]);
  161.     if (sdrag) return 1;
  162.     return Fl_Group::handle(event);
  163.   }
  164.  
  165.   case FL_LEAVE:
  166.     set_cursor(this, FL_CURSOR_DEFAULT);
  167.     break;
  168.  
  169.   case FL_DRAG:
  170.     // This is necessary if CONSOLIDATE_MOTION in Fl_x.C is turned off:
  171.     // if (damage()) return 1; // don't fall behind
  172.   case FL_RELEASE: {
  173.     if (!sdrag) return 0; // should not happen
  174.     Fl_Widget* r = resizable(); if (!r) r = this;
  175.     int newx;
  176.     if (sdrag&DRAGH) {
  177.       newx = Fl::event_x()-sdx;
  178.       if (newx < r->x()) newx = r->x();
  179.       else if (newx > r->x()+r->w()) newx = r->x()+r->w();
  180.     } else
  181.       newx = sx;
  182.     int newy;
  183.     if (sdrag&DRAGV) {
  184.       newy = Fl::event_y()-sdy;
  185.       if (newy < r->y()) newy = r->y();
  186.       else if (newy > r->y()+r->h()) newy = r->y()+r->h();
  187.     } else
  188.       newy = sy;
  189.     position(sx,sy,newx,newy);
  190.     return 1;}
  191.  
  192.   }
  193.  
  194.   return Fl_Group::handle(event);
  195. }
  196.  
  197. //
  198. // End of "$Id: Fl_Tile.cxx,v 1.5.2.1 1999/05/25 05:33:56 bill Exp $".
  199. //
  200.